{
 TExceptionHandler is actually an Exception logger but can also hide or not
 the standard message displayed when an exception occurs.
 It keeps a log writing the Form and the ActiveControl when the exception occured ,
 also the date&time the computername and the current username.
 Works for D7 but also for D6 i think not tested thow.


 For any comments or suggestions please e-mail at Unixxas@yahoo.com or Gtrifidis@yahoo.com
 either will do fine...
}

unit ExceptionHandler;

interface

uses
  SysUtils, Classes,AppEvnts,TypInfo,Windows,Forms;

Const
  LogFileName='EHandlerLog.log';
  EHandler   ='TExceptionHandler';
  Link       ='->';
  ErrorProp  ='ErrorCode';

type
  TExceptionHandler = class(TComponent)
  private
    { Private declarations }
    FActive:Boolean;
    FShowException:Boolean;
    FAppEvents:TApplicationEvents;
    FLogFile:TStrings;
    FLogFileDir:String;//if prop='' then the dir is the current dir;
  protected
    { Protected declarations }
    procedure HandleException(Sender:TObject;E:Exception);
    function  WriteExceptionInfo(Sender:TObject;E:Exception):String;
    function  GetComputerName: string;
    function  GetCurrentUserName: string;
  public
    { Public declarations }
    constructor Create(AOwner:TComponent);override;
    destructor  Destroy;override;
  published
    { Published declarations }
    property Active:    Boolean    read FActive        write FActive;
    property LogFileDir:String     read FLogFileDir    write FLogFileDir;
    property ShowException:Boolean read FShowException write FShowException;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TExceptionHandler]);
end;

{ TExceptionHandler }

constructor TExceptionHandler.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FActive:=True;
  if FActive then
    begin
      FAppEvents:=TApplicationEvents.Create(Self);
      FAppEvents.OnException:=HandleException;
      FLogFile:=TStringList.Create;
      if FLogFileDir<>'' then
        begin
          if  FileExists(FLogFileDir+LogFileName) then
            FLogFile.LoadFromFile(FLogFileDir+LogFileName);
        end
      else
        begin
          if FileExists(GetCurrentDir+'\'+LogFileName) then
            FLogFile.LoadFromFile(FLogFileDir+LogFileName);
        end;
    end;
end;

destructor TExceptionHandler.Destroy;
begin
  if Assigned(FLogFile) then
    begin
      try
        if FLogFileDir<>'' then
          FLogFile.SaveToFile(FLogFileDir+LogFileName)
        else
          FLogFile.SaveToFile(GetCurrentDir+'\'+LogFileName);
      except
        raise Exception.Create('Could not save Log File!!!');
      end;
    end;
  FAppEvents.Free;
  FLogFile.Free;
  inherited;
end;

procedure TExceptionHandler.HandleException(Sender: TObject; E: Exception);
begin
  if Assigned(FLogFile) then
    begin
      if FActive then
        begin
          FLogFile.Add(' ');
          FLogFile.Add(WriteExceptionInfo(Sender,E));
          FLogFile.Add(' ');
        end;
    end;
  if FShowException then
    begin
      MessageBox(HWND(nil),PChar(WriteExceptionInfo(Sender,E)),
      PChar(Application.Title),MB_OK+MB_ICONERROR);
    end;
end;

function TExceptionHandler.WriteExceptionInfo(Sender:TObject;E: Exception): String;
begin
  Result:='';
  if IsPublishedProp(E,ErrorProp) then
    begin
      Result:=Format(EHandler+Link+'From:%s'+Link+'Active Control:%s'+Link+' with message:%s'+Link+
        'Errorcode:%d'+Link+' Date:%s Time:%s'+Link+'ComputerName:%s UserName:%s',
        [Sender.ClassName,Screen.ActiveForm.ActiveControl.Name,E.Message,GetPropValue(E,ErrorProp),DateToStr(Date),TimeToStr(Now),GetComputerName,GetCurrentUserName]);
    end
  else
    begin
      Result:=Format(EHandler+Link+'From:%s'+Link+'Active Control:%s'+Link+' with message:%s'+Link+
      'Date:%s Time:%s'+Link+'ComputerName:%s UserName:%s',
      [Sender.ClassName,Screen.ActiveForm.ActiveControl.Name,E.Message,DateToStr(Date),TimeToStr(Now),GetComputerName,GetCurrentUserName]);
    end;
end;

function TExceptionHandler.GetComputerName: string;
var
  buffer: array[0..MAX_COMPUTERNAME_LENGTH + 1] of Char;
  Size: Cardinal;
begin
  Size := MAX_COMPUTERNAME_LENGTH + 1;
  Windows.GetComputerName(@buffer, Size);
  Result := StrPas(buffer);
end;

function TExceptionHandler.GetCurrentUserName: string;
const
  cnMaxUserNameLen = 254;
var
  sUserName: string;
  dwUserNameLen: DWORD;
begin
  dwUserNameLen := cnMaxUserNameLen - 1;
  SetLength(sUserName, cnMaxUserNameLen);
  GetUserName(PChar(sUserName), dwUserNameLen);
  SetLength(sUserName, dwUserNameLen);
  Result := sUserName;
end;



end.
